#include "game.hpp"

Game::Game() : KeyBoard(), UI() {
  for (int i = 0; i < Robot_Number; i++) {
    Robot_Blue[i] = new Robot((Config_Robot_Name_t)i, CONFIG_COLOR_BLUE);
    Robot_Red[i] = new Robot((Config_Robot_Name_t)i, CONFIG_COLOR_RED);
  }
  red = NOT_SELECT;
  blue = NOT_SELECT;
}

Game::~Game() {
  for (int i = 0; i < Robot_Number; i++) {
    delete Robot_Blue[i];
    delete Robot_Red[i];
  }
}

void Game::Refresh() {
  for (int i = 0; i < Robot_Number; i++) {
    // show Robot_Blue[i]
    // show Robot_Red[i]
  }
}

void Game::Show(Robot *robot, Config_Color_t color) {
  if (robot->Life())
    UI_Show(robot->Name(), color, robot->Address(), robot->Target(),
            robot->Angle(), robot->HP());
}

bool Game::Key_Scan() {
  Config_Key_Behavior_t behav;
  if ((behav = Scan()) != KEY_BEHAVIOR_NULL) {
    switch (behav) {
      case BLUE_SELECT_HERO:
        blue = SELECT_HERO;
        break;
      case BLUE_SELECT_INFANTRY:
        blue = SELECT_INFANTRY;
        break;
      case BLUE_FORE:
        switch (blue) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Blue[Hero]->ChangeTarget(0, -SINGLE_AREA_LENGTH);
            break;
          case SELECT_INFANTRY:
            Robot_Blue[Infantry]->ChangeTarget(0, -SINGLE_AREA_LENGTH);
            break;
          default:
            break;
        }
        break;
      case BLUE_BACK:
        switch (blue) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Blue[Hero]->ChangeTarget(0, SINGLE_AREA_LENGTH);
            break;
          case SELECT_INFANTRY:
            Robot_Blue[Infantry]->ChangeTarget(0, SINGLE_AREA_LENGTH);
            break;
          default:
            break;
        }
        break;
      case BLUE_LEFT:
        switch (blue) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Blue[Hero]->ChangeTarget(-SINGLE_AREA_LENGTH, 0);
            break;
          case SELECT_INFANTRY:
            Robot_Blue[Infantry]->ChangeTarget(-SINGLE_AREA_LENGTH, 0);
            break;
          default:
            break;
        }
        break;
      case BLUE_RIGHT:
        switch (blue) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Blue[Hero]->ChangeTarget(SINGLE_AREA_LENGTH, 0);
            break;
          case SELECT_INFANTRY:
            Robot_Blue[Infantry]->ChangeTarget(SINGLE_AREA_LENGTH, 0);
            break;
          default:
            break;
        }
        break;
      case RED_SELECT_HERO:
        red = SELECT_HERO;
        break;
      case RED_SELECT_INFANTRY:
        red = SELECT_INFANTRY;
        break;
      case RED_FORE:
        switch (red) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Red[Hero]->ChangeTarget(0, -SINGLE_AREA_LENGTH);
            break;
          case SELECT_INFANTRY:
            Robot_Red[Infantry]->ChangeTarget(0, -SINGLE_AREA_LENGTH);
            break;
          default:
            break;
        }
        break;
      case RED_BACK:
        switch (red) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Red[Hero]->ChangeTarget(0, SINGLE_AREA_LENGTH);
            break;
          case SELECT_INFANTRY:
            Robot_Red[Infantry]->ChangeTarget(0, SINGLE_AREA_LENGTH);
            break;
          default:
            break;
        }
        break;
      case RED_LEFT:
        switch (red) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Red[Hero]->ChangeTarget(-SINGLE_AREA_LENGTH, 0);
            break;
          case SELECT_INFANTRY:
            Robot_Red[Infantry]->ChangeTarget(-SINGLE_AREA_LENGTH, 0);
            break;
          default:
            break;
        }
        break;
      case RED_RIGHT:
        switch (red) {
          case NOT_SELECT:
            break;
          case SELECT_HERO:
            Robot_Red[Hero]->ChangeTarget(SINGLE_AREA_LENGTH, 0);
            break;
          case SELECT_INFANTRY:
            Robot_Red[Infantry]->ChangeTarget(SINGLE_AREA_LENGTH, 0);
            break;
          default:
            break;
        }
        break;
      case Quit:
        return true;
      default:
        break;
    }
  }
  return false;
}

void Game::Hit_Scan() {
  for (int i = 0; i < Robot_Number; i++) {
    float red_min = SCREEN_WIDTH;
    float blue_min = SCREEN_WIDTH;
    int red_min_number = 0;
    int blue_min_number = 0;
    for (int t = 0; t < Robot_Number; t++) {
      if (Robot_Red[(Config_Robot_Name_t)i]->Life() &&
          Robot_Blue[(Config_Robot_Name_t)t]->Life())
        if (red_min > Robot_Red[(Config_Robot_Name_t)i]->Distance(
                          Robot_Blue[(Config_Robot_Name_t)t])) {
          red_min = Robot_Red[(Config_Robot_Name_t)i]->Distance(
              Robot_Blue[(Config_Robot_Name_t)t]);
          red_min_number = t;
        }

      if (Robot_Blue[(Config_Robot_Name_t)i]->Life() &&
          Robot_Red[(Config_Robot_Name_t)t]->Life())
        if (blue_min > Robot_Blue[(Config_Robot_Name_t)i]->Distance(
                           Robot_Red[(Config_Robot_Name_t)t])) {
          blue_min = Robot_Blue[(Config_Robot_Name_t)i]->Distance(
              Robot_Red[(Config_Robot_Name_t)t]);
          blue_min_number = t;
        }
    }
    if (Robot_Blue[(Config_Robot_Name_t)i]->Life())
      switch (Robot_Blue[(Config_Robot_Name_t)i]->Scan(
          Robot_Red[(Config_Robot_Name_t)blue_min_number])) {
        case Scan_Not_Found:
          break;
        case Scan_Detect:
          break;
        case Scan_Hit:
          Robot_Blue[(Config_Robot_Name_t)i]->Hit(
              Robot_Red[(Config_Robot_Name_t)blue_min_number]);
      }

    if (Robot_Red[(Config_Robot_Name_t)i]->Life())
      switch (Robot_Red[(Config_Robot_Name_t)i]->Scan(
          Robot_Blue[(Config_Robot_Name_t)red_min_number])) {
        case Scan_Not_Found:
          break;
        case Scan_Detect:
          break;
        case Scan_Hit:
          Robot_Red[(Config_Robot_Name_t)i]->Hit(
              Robot_Blue[(Config_Robot_Name_t)red_min_number]);
      }
  }
}

void Game::Start() {
  while (true) {
    UI_Start();
    Delay();
    if (Key_Scan()) break;
  }
  while (true) {
    if (Key_Scan()) return;

    Hit_Scan();

    for (int i = 0; i < Robot_Number; i++) {
      if (Robot_Red[(Config_Robot_Name_t)i]->Life())
        Robot_Red[(Config_Robot_Name_t)i]->Move();
      if (Robot_Blue[(Config_Robot_Name_t)i]->Life())
        Robot_Blue[(Config_Robot_Name_t)i]->Move();
    }

    Clear();

    for (int i = 0; i < Robot_Number; i++) {
      if (Robot_Blue[(Config_Robot_Name_t)i]->Life())
        Show(Robot_Blue[(Config_Robot_Name_t)i], CONFIG_COLOR_BLUE);
      Robot_Blue[(Config_Robot_Name_t)i]->traj.time++;
      if (Robot_Blue[(Config_Robot_Name_t)i]->Died())
        Robot_Blue[(Config_Robot_Name_t)i]->Stop();
      if (Robot_Blue[(Config_Robot_Name_t)i]->Traj_Available()) {
        Bullet_Casing(&(Robot_Blue[(Config_Robot_Name_t)i]->traj.origin),
                      &(Robot_Blue[(Config_Robot_Name_t)i]->traj.target),
                      Robot_Blue[(Config_Robot_Name_t)i]->traj.time);
      }
      if (Robot_Red[(Config_Robot_Name_t)i]->Life())
        Show(Robot_Red[(Config_Robot_Name_t)i], CONFIG_COLOR_RED);
      Robot_Red[(Config_Robot_Name_t)i]->traj.time++;
      if (Robot_Red[(Config_Robot_Name_t)i]->Died())
        Robot_Red[(Config_Robot_Name_t)i]->Stop();
      if (Robot_Red[(Config_Robot_Name_t)i]->Traj_Available()) {
        Bullet_Casing(&(Robot_Red[(Config_Robot_Name_t)i]->traj.origin),
                      &(Robot_Red[(Config_Robot_Name_t)i]->traj.target),
                      Robot_Red[(Config_Robot_Name_t)i]->traj.time);
      }
    }

    if (Robot_Blue[Base]->HP() <= 0) {
      UI_End(CONFIG_COLOR_RED);
      while (true) {
        if (Key_Scan()) return;
        Delay();
      }
    }
    if (Robot_Red[Base]->HP() <= 0) {
      UI_End(CONFIG_COLOR_BLUE);
      while (true) {
        if (Key_Scan()) return;
        Delay();
      }
    }
    Delay();
  }
}
